#pragma once
#include<iostream>
#include<string.h>

using namespace std;
template<typename T>
class Vector
{
public:
	Vector()
	{
		_ptr = NULL;
		_size = NULL;
		_capacity = NULL;
	}


	Vector(T*arr,size_t size)
		:_ptr(new T[size])
		,_size(_ptr+size)
		,_capacity(_ptr + size)
	{
		for (size_t i=0;i<size;i++)
		{
			_ptr[i] = arr[i];
		}
	}


	Vector(Vector& v)
	{
		size_t size = v.Size();
		_ptr = new T[size];
		_size = _ptr + size;
		_capacity = _size;
		memmove(_ptr,v._ptr,sizeof(T)*v.Size());
	}


	void CheckCapacity()
	{
		if ((_capacity - _size) <= 0)
		{
			size_t ret = Capacity();
			size_t size = Size();
			T* tmp = new T[ret*2+3];
			for (size_t i=0;i<size;i++)
			{
				tmp[i] = _ptr[i];
			}
			delete[] _ptr;
			_ptr = tmp;
			_size = _ptr + size;
			_capacity = _ptr + ret*2;
			
		}
	}


	Vector& operator=(const Vector& s)
	{
		if (this != &s)
		{
			size_t size = s.Size();
			if (_ptr)
				delete[] _ptr;

			_ptr = new T[size];
			for (size_t i=0;i<size;i++)
			{
				_ptr[i] = s._ptr[i];
			}
			_size = _ptr+size;
			_capacity = _ptr + s.Capacity();
		}
		return *this;
	}
	

	~Vector()
	{
		if(_ptr)
		{
			delete[]_ptr;
			_ptr = NULL;
			_size = NULL;
			_capacity = NULL;
		}
	}


	size_t Size()const
	{
		return _size - _ptr;
	}


	size_t Capacity()const
	{
		return _capacity - _ptr;
	}

	void PushBack(const T& data)
	{
		CheckCapacity();
		size_t size = Size();
		_ptr[size] = data;
		_size++;
	}

	template<class T>
	friend ostream& operator<<(ostream &_cout, const Vector<T>& s)
	{
		size_t size = s.Size();
		for (size_t i = 0;i<size;i++)
		{
			_cout<<s._ptr[i]<<"---->";
		}
		cout<<"over"<<endl;
		return _cout;
	}

	void Display()
	{
		for (size_t i = 0;i<Size();i++)
		{
			cout<<_ptr[i]<<"---->";
		}
		cout<<"over"<<endl;
	}

	void Popback()
	{
		_size--;
	}

	void Insert(size_t pos,T data)
	{
		size_t size = Size();
		 if (pos>0&&pos <= size)
		 {
			 CheckCapacity();
			for(size_t i=size;i>=pos-1;i--)
			{
				_ptr[i+1] = _ptr[i];
			}
			_ptr[pos-1] = data;
			_size++;
		 }
	}


	void Erase(size_t pos)
	{
		size_t size = Size();
		if (pos>0&&pos<size)
		{
			memmove(_ptr+pos-1,_ptr+pos,(size-pos)*sizeof(T));
			_size--;
		}
	}
	bool Empty()const
	{
		if (_size == _ptr)
		{
			return true;
		}
		else
			return false;
	}

	void Resize(size_t newSize, const T& data = T())
	{
		size_t size = Size();
		size_t capacity = Capacity();
		if (newSize < size)
			_size = _ptr + newSize;
		
		else if(newSize>size&&newSize<capacity)
			CheckCapacity();
		else 
		{
			for (size_t i=size;i<newSize;i++)
				_ptr[i] = data;
			_size = _ptr + newSize;
		}
	}


	T& operator[](size_t index)
	{
		if (index > 0&&index < Size())
		{
			return _ptr[index];
		}
		else
			exit(EXIT_FAILURE);
	}

	const T& operator[](size_t index)const
	{
		if (index > 0&&index < Size())
		{
			return _ptr[index];
		}
		else
			exit(EXIT_FAILURE);
	}


	T& Front()
	{
		return _ptr[0];
	}


	const T& Front()const
	{
		return _ptr[0];
	}

	T& Back()
	{
		return _ptr[Size()];
	}

	const T& Back()const
	{
		return _ptr[Size()];
	}


	void Clear()
	{
		_size = _ptr;
	}

private:
	T* _ptr;
	T* _size;
	T* _capacity;
};
